home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / DISK / TWISTER2 / MMTWST.C < prev    next >
Encoding:
C/C++ Source or Header  |  1985-11-19  |  34.8 KB  |  883 lines

  1. /*
  2.  *        Megamax C inline ASM version of Twister.
  3.  *        Converted from AS68 format  dlm  12/14/86.
  4.  *        AS68 version by David Small before that date.
  5.  *        Used for the MegAMin HD backup program.
  6.  */
  7.  
  8. /* routine that are callable from C are: */
  9. extern twister();
  10.  
  11. /* global variables */
  12. int thedisk, dblsided, sectoroffset;   /* input parameters */
  13. long buffer;
  14.  
  15. int badflag;                           /* bad sector error flag */
  16.  
  17. /* local variables */
  18. static int theside, thetrack, twistsectorno, sectorno, retrycnt,
  19.            cdev, ctrack, csect, cside, ccount, A7t, interlv,
  20.            virgin, def_error, curr_err;
  21. static long cdma, edma, tmpdma, saveA2;
  22.  
  23. /* now the defines (AS68 equ's) */
  24.  
  25. /*   tunable values */
  26. #define retries   2           /* default # of retries -1 */
  27. #define midretry  1           /* "middle" retry, when to reseek  */
  28. #define timeout   0x40000     /* short timeout, motor already on */
  29. #define ltimeout  0x60000     /* long timeout, to startup motor  */
  30.  
  31. /*   Floppy state variables in DSB: RAM usage */
  32. #define recal     0xff00      /* recalibrate flag                */
  33. #define dcurtrack 0           /* current track number            */
  34. #define dseekrt   dcurtrack+2 /* seek rate                       */
  35. #define dsbsiz    dseekrt+2   /* size of a DSB                   */
  36.  
  37. /* hardware equates */
  38. /* DMA chip         */
  39. #define diskctl     0xffff8604     /* disk controller data access */
  40. #define fifo        0xffff8606     /* DMA mode control / status   */
  41. #define dmahigh     0xffff8609     /* DMA base high               */
  42. #define dmamid      0xffff860b     /* DMA base mid                */
  43. #define dmalow      0xffff860d     /* DMA base low                */
  44.  
  45. /* 1170 select values    */
  46. #define cmdreg      0x80           /* select command register    */
  47. #define trkreg      0x82           /* select track register      */
  48. #define secreg      0x84           /* select sector register     */
  49. #define datareg     0x86           /* select data register       */
  50.  
  51. /* GI sound chip (drive a/b select lines and side select) */
  52. #define giselect    0xffff8800     /* (W) sound chip register select */
  53. #define giread      0xffff8800     /* (R) sound chip read data   */
  54. #define giwrite     0xffff8802     /* (W) sound chip write data  */
  55. #define giporta     0x0e           /* GI register # for i/o port A */
  56.  
  57. /* 68901 mfp chip */
  58. #define mfp         0xfffffa00     /* mfp base                   */
  59. #define gpip        mfp+1          /* general purpose i/o        */
  60.  
  61. /* ROM burn dates */
  62. #define old_rom  0x11201985L
  63. #define new_rom  0x04221987L
  64.  
  65. #define rom_date 0x00fc0018L        /* rom burn date address */
  66.  
  67. /* misc defines */
  68. #define seekrate 3
  69. #define dsb0old  0xa06
  70. #define dsb0new  0xa4c        /* for the Mega ROMs */
  71. #define dsb1old  0xa0a
  72. #define dsb1new  0xa50
  73. #define flock    0x43e
  74.  
  75. asm {          /* start of inline ASM */
  76.  
  77. /*
  78.  *   All the following is munged code from AS68 (that's why the
  79.  *   weird format).  The AS68 code was munged from the BIOS
  80.  *   source.  And most of this is from the FDC article in Start
  81.  *   issue number 3.
  82.  *
  83.  *   Anyway, we apologize for the mess, but heh it works.
  84.  *
  85.  *   Oh yes.  The labels are usually on nops, not empty lines.  Thats
  86.  *   because AS68 occasionally pukes on labels on empty lines.  And
  87.  *   I didn't take the time to remove them.  (Megamax doesn't care.)
  88.  *
  89.  */
  90.  
  91. ;****************************************************************
  92. ; Twister: Faster formatter (zipformat) hack.  MM version       *
  93. ; Copyright (c) 1986, 1987 START Magazine (as usual)            *
  94. ; Written by David Y. Small & Dan Moore                         *
  95. ;****************************************************************
  96. ;                                                               *
  97. ;               Dedication:                                     *
  98. ;                                                               *
  99. ;     For Bill The Cat: because he's twisted, too.              *
  100. ;                                                               *
  101. ;****************************************************************
  102. ;
  103. ; code begins.
  104. ;
  105. ;  PASS ME THIS STUFF DAN! Then SHAVE! For God's sakes! What
  106. ; are you trying to do, look like Fidel Castro?
  107. ;
  108. ; And get SOME BEER in here okay? Sheesh!
  109. ;
  110. ; input integers (if coming from C):
  111. ;
  112. ; dblsided: 0000 or ffff
  113. ; thedisk: 0 = a, 1 = b
  114. ;*************************************************************
  115.  
  116.  
  117. ;********************************************************
  118. ; Frammatter                                            *
  119. ;********************************************************
  120. twister:  move.l    A2, saveA2(A4)      ; everything else saved by the Supexec
  121.  
  122.         clr.w       badflag(A4)         ; assume no errors
  123. ;
  124. ;*** Init vars for formatting loop
  125. ;
  126.         move.w  #0,thetrack(A4)     ; start at track 0
  127.  
  128.         move.w  #1,twistsectorno(A4) ; twister value
  129.                                
  130. trackloop: nop                  ; comes here for subseq tracks
  131.  
  132.  
  133. ;***** FRONT SIDE ***********
  134. ;**** Setup stack: .. based on read sec command, tweaked for frammat
  135.  
  136.         move.w  #0xe5e5,-(A7)    ; virgin data -- e5's work okay
  137.         move.l  #0x87654321,-(A7) ; magic # to make format work / fmt only
  138.         move.w  #1,-(A7)        ; sector interleave factor / fmt only
  139.         move.w  #0,-(A7)        ; ** side.w (relevant) / side: FRONT
  140.         move.w  thetrack(A4),-(A7)  ; ** track.w (relevant) / same
  141.         move.w  #10,-(A7)       ; sector.w (irrelevant) / sectors per track
  142.         move.w  thedisk(A4),-(A7)   ; ** device.w  (relevant) / same
  143.         move.l  #0,-(A7)        ; dummy.l (irreleveant) / same
  144.         move.l  buffer(A4),-(A7)   ; ** buffer address.l (relevant) / same
  145.         jsr     _flopfmt
  146.         adda.l  #24,A7          ; Fix stack.
  147. ;****
  148. ; Jazz twistsectorno(A4). Look at what it ended up as; set it to
  149. ; the next track twist depending on that.
  150. ;
  151. ; It will end up as "+1" from the last sector formatted, because
  152. ; the formatter bumps it up.
  153. ;
  154.         cmpi.w  #1,twistsectorno(A4)        ; 0-1 transition
  155.         beq     fgoto1
  156.         cmpi.w  #9,twistsectorno(A4)        ; 1-2 transition
  157.         beq     fgoto2
  158.         cmpi.w  #7,twistsectorno(A4)        ; 2-3 transition
  159.         beq     fgoto3
  160.         cmpi.w  #5,twistsectorno(A4)        ; 3-4 transition
  161.         beq     fgoto4
  162.         cmpi.w  #3,twistsectorno(A4)        ; 4-0 transition
  163.         beq     fgoto0
  164.         
  165.         dc.b   0x4a
  166.         dc.b   0xfc                 ; oops, die (illegal instruction)
  167. ;*****
  168. ; Really class coding, eh? Oh,well, it's easy and it works, which
  169. ; twelve other fancy ways of doing this *don't*.
  170. ;
  171. fgoto1: move.w  #0x9,twistsectorno(A4)       ; 9,a,1,2,3,4,5,6,7,8
  172.         bra     fkeepformatting
  173. fgoto2: move.w  #0x7,twistsectorno(A4)       ; 7,8,9,a,1,2,3,4,5,6
  174.         bra     fkeepformatting
  175. fgoto3: move.w  #0x5,twistsectorno(A4)       ; 5,6,7,8,9,a,1,2,3,4
  176.         bra     fkeepformatting
  177. fgoto4: move.w  #0x3,twistsectorno(A4)       ; 3,4,5,6,7,8,9,a,1,2
  178.         bra     fkeepformatting
  179. fgoto0: move.w  #0x1,twistsectorno(A4)       ; 1,2,3,4,5,6,7,8,9,a
  180.         bra     fkeepformatting
  181.         nop
  182. ;*****
  183. fkeepformatting: nop
  184. ;*****
  185. ; now, do a verify on those sectors.
  186. ;**** Setup stack: .. based on read sec command, tweaked for frammat
  187.  
  188.         tst.w   sectoroffset(A4)   ; no verify if 11 to 20 sector numbering
  189.         bne     nover1
  190.  
  191.         move.w  #0xa,-(A7)       ; count.w 2
  192.         move.w  #0,-(A7)        ; ** side.w (relevant) / side: FRONT 4
  193.         move.w  thetrack(A4),-(A7)  ; ** track.w (relevant) / same 6
  194.         move.w  #0x1,-(A7)       ; sector.w (relevant) / starting sector 8
  195.         move.w  thedisk(A4),-(A7)   ; ** device.w  (relevant) / same 0xa
  196.         move.l  #0,-(A7)        ; dummy.l (irreleveant) / same 0xe
  197.         move.l  buffer(A4),-(A7)   ; ** buffer address.l (relevant) / same 0x12
  198.  
  199.         move.w  #19,-(A7)       ; do BIOS _flopver 0x14
  200.         trap    #14
  201.         adda.l  #20, A7        ; fix stack.
  202.  
  203.         tst.l   D0
  204.         bne     badsecs
  205.  
  206. ;****
  207.  
  208. ;***** BACK SIDE ******       (How kinky Dave.  What _are_ you talking about?)
  209.  
  210. nover1:   tst.w   dblsided(A4)
  211.           beq     nobackside
  212.  
  213. ;**** Setup stack: .. based on read sec command, tweaked for frammat
  214.  
  215.         move.w  #0xe5e5,-(A7)    ; virgin data -- e5's work okay
  216. ; and with a virgin.  My, you really are weird Dave.
  217.         move.l  #0x87654321,-(A7) ; magic # to make format work / fmt only
  218.         move.w  #1,-(A7)        ; sector interleave factor / fmt only
  219.         move.w  #1,-(A7)        ; ** side.w (relevant) / side: BACK
  220.         move.w  thetrack(A4),-(A7)  ; ** track.w (relevant) / same
  221.         move.w  #10,-(A7)       ; sector.w (irrelevant) / sectors per track
  222.         move.w  thedisk(A4),-(A7)   ; ** device.w  (relevant) / same
  223.         move.l  #0,-(A7)        ; dummy.l (irreleveant) / same
  224.         move.l  buffer(A4),-(A7)   ; ** buffer address.l (relevant) / same
  225.         jsr     _flopfmt
  226.         adda.l  #24,A7          ; Fix stack.
  227. ;*****
  228. ;
  229. ; Jazz twistsectorno(A4). Look at what it ended up as; set it to
  230. ; the next track twist depending on that.
  231. ;
  232. ; It will end up as "+1" from the last sector formatted, because
  233. ; the formatter bumps it up.
  234. ;
  235.         cmpi.w  #1,twistsectorno(A4)        ; 0-1 transition
  236.         beq     goto1
  237.         cmpi.w  #9,twistsectorno(A4)        ; 1-2 transition
  238.         beq     goto2
  239.         cmpi.w  #7,twistsectorno(A4)        ; 2-3 transition
  240.         beq     goto3
  241.         cmpi.w  #5,twistsectorno(A4)        ; 3-4 transition
  242.         beq     goto4
  243.         cmpi.w  #3,twistsectorno(A4)        ; 4-0 transition
  244.         beq     goto0
  245.  
  246.         dc.b    0x4a
  247.         dc.b    0xfc                 ; oops, die
  248.  
  249. ;
  250. goto1:  move.w  #0x9,twistsectorno(A4)       ; 9,a,1,2,3,4,5,6,7,8
  251.         bra     keepformatting
  252. goto2:  move.w  #0x7,twistsectorno(A4)       ; 7,8,9,a,1,2,3,4,5,6
  253.         bra     keepformatting
  254. goto3:  move.w  #0x5,twistsectorno(A4)       ; 5,6,7,8,9,a,1,2,3,4
  255.         bra     keepformatting
  256. goto4:  move.w  #0x3,twistsectorno(A4)       ; 3,4,5,6,7,8,9,a,1,2
  257.         bra     keepformatting
  258. goto0:  move.w  #0x1,twistsectorno(A4)       ; 1,2,3,4,5,6,7,8,9,a
  259.         bra     keepformatting
  260.         nop
  261. ;
  262. keepformatting: nop             ; entry after twisting.
  263. ;
  264.  
  265. ;**** Setup stack: .. based on read sec command, tweaked for frammat
  266.         
  267.         tst.w   sectoroffset(A4)   ; no verify for strange sector numbers
  268.         bne     nobackside
  269.  
  270.         move.w  #0xa,-(A7)       ; count.w 2
  271.         move.w  #1,-(A7)        ; ** side.w (relevant) / side: BACK 4
  272.         move.w  thetrack(A4),-(A7)  ; ** track.w (relevant) / same 6
  273.         move.w  #0x1,-(A7)       ; sector.w (relevant) / starting sector # 8
  274.         move.w  thedisk(A4),-(A7)   ; ** device.w  (relevant) / same 0xa
  275.         move.l  #0,-(A7)        ; dummy.l (irreleveant) / same 0xe
  276.         move.l  buffer(A4),-(A7)   ; ** buffer address.l (relevant) / same 0x12
  277.  
  278.         move.w  #19,-(A7)       ; do BIOS _flopver 0x14 (why not)
  279.         trap    #14
  280.         adda.l  #20, A7         ; fix stack
  281.  
  282.         tst.l   D0
  283.         bne     badsecs         ; wham
  284.  
  285. ;****
  286. nobackside: nop                 ; entry if not DS  (well at least this isn't kinky Dave)
  287.  
  288. ; add 1 to thetrack. If 80, quit.
  289.         addi.w   #1, thetrack(A4)
  290.         cmpi.w  #80, thetrack(A4)
  291.         bne     trackloop       ; "do another"
  292.  
  293.         bra     gemexit         ; Continue, etc, and so forth
  294.  
  295. ;*********
  296. badsecs:  move.w #0xffff, badflag(A4)  ; bad sectors found
  297.  
  298. ;**************
  299. ;
  300. ; End. Exit to calling routine.
  301. ;
  302. gemexit:  movea.l saveA2(A4), A2  ; only reg not saved by Supexec
  303.           rts
  304.  
  305. ;******************************************************
  306. ;
  307. ;------------------------------------------------------------------------
  308. ;       130-ST / 520-ST                                                 :
  309. ;       Floppy Disk Driver                                              :
  310. ;       (C)1985 Atari Corp.                                             :
  311. ;       From the FDC article (Start issue 3); shortened to just         :
  312. ;       the formatter routine and the low level I/O.                    :
  313. ;                                                                       :
  314. ;------------------------------------------------------------------------
  315. ;
  316. ;************************************************************
  317. ;
  318. ; _flopfmt - format a track
  319. ; Passed (on the stack):
  320. ;       0x1a(A7) initial sector data
  321. ;       0x16(A7) magic number
  322. ;       0x14(A7) interleave
  323. ;       0x12(A7) side
  324. ;       0x10(A7) track
  325. ;        0xe(A7) A7t(A4)
  326. ;        0xc(A7) drive
  327. ;        0x8(A7) pointer to state block
  328. ;        0x4(A7) dma address
  329. ;        0x0(A7) [return]
  330. ;
  331. ; Returns:      EQ: track successfully written.  Zero.W-terminated list of
  332. ;               bad sectors left in buffer (they might /all/ be bad.)
  333. ;
  334. ;               NE: could not write track (write-protected, drive failure,
  335. ;               or something catastrophic happened).
  336. ;-
  337. _flopfmt:
  338.         cmpi.l   #0x87654321, 0x16(A7)      ; check for magic# on stack
  339.         bne     flopfail                ; no magic, so we just saved the world
  340. ;       bsr     change                  ; check for disk flip
  341. ;       moveq   #e_error,D0             ; set default error number
  342.         bsr     floplock                ; lock floppies, setup parms
  343.         bsr     select                  ; select drive and side
  344.         move.w  0xe(A7),A7t(A4)              ; save sectors-per-track
  345.         move.w  0x14(A7),interlv(A4)         ; save interleave factor
  346.         move.w  0x1a(A7),virgin(A4)          ; save initial sector data
  347.  
  348. ;--- put drive into "changed" mode
  349. ;       moveq   #m_changed,D0           ; D0 = "CHANGED"
  350. ;       bsr     setdmode                ; set media change mode
  351.  
  352. ;--- seek to track (hard seek):
  353. ;debug* move.l  #0xff00ff00,0xf8030
  354.         bsr     hseek                   ; hard seek to 'ctrack'
  355. ;debug* move.l  #0x00000000,0xf8030
  356.         bne     flopfail                ; (return error on seek failure)
  357.         move.w  ctrack(A4),dcurtrack(A1)    ; record current track#
  358.  
  359. ;--- format track, then verify it:
  360. ;*      move.w  #e_error,curr_err(A4)(A5)   ; vanilla error mode
  361. ;debug* move.l  #0xff00ff00,0xfA030
  362.         bsr     fmtrack                 ; format track
  363. ;debug* move.l  #0x0,0xfA030
  364.  
  365.         bne     flopfail                ; (return error on seek failure)
  366.         bra     flopok
  367.  
  368.  
  369. ;****************************
  370. ;+
  371. ; fmtrack - format a track. Tweaked for skewed interleave.
  372. ;
  373. ; Passed:       variables setup by _flopfmt
  374. ; Returns:      NE on failure, EQ on success
  375. ; Uses:         almost everything
  376. ; Called-by:    _flopfmt
  377. ;
  378. ;-
  379. fmtrack:
  380. ;*      move.w  #e_write,def_error(A4)  ; set default error number
  381.         move.w  #1,D3                   ; start with sector 1, first pass
  382. ;**
  383.         movea.l  cdma(A4),A2            ; A2 =  prototyping area
  384. ; Lay down beginning of track
  385.  
  386.         move.w  #60-1,D1                ; 60 x 0x4e (track leadin)
  387.         move.b  #0x4e,D0
  388.         bsr     wmult
  389. ; Repeat 10 times: sector data.
  390.         move.w  #1,sectorno(A4)             ; how many secs written
  391. ; Note that twistsectorno is initialized out of this routine.
  392. ;--- address mark
  393. secloop: nop
  394. ;
  395. ot1:    move.w  #12-1,D1                ; 12 x 0x00
  396.         clr.b   D0
  397.         bsr     wmult
  398.         move.w  #3-1,D1                 ; 3 x 0xf5
  399.         move.b  #0xf5,D0
  400.         bsr     wmult
  401.         move.b  #0xfe,(A2)+              ; 0xfe -- address mark intro
  402.         move.b  ctrack+1(A4),(A2)+          ; track# - low half of word
  403.         move.b  cside+1(A4),(A2)+           ; side# - low half of word
  404.  
  405. ;* #1: just use a plain sector number
  406. ;*      move.b  D4,(A2)+                ; sector#
  407.  
  408. ;* #2: use a twisted sector number
  409. ;*      move.b  twistsectorno+1(A4),(A2)+   ; new: sector #.
  410.  
  411.         move.w  twistsectorno(A4),D0        ; fetch     1-10 sector #
  412. ;
  413. ; Note that meg-a-minute backup uses sectors # 11-20 to force GEM
  414. ; not to use MM disks.
  415. ;
  416.         add.w   sectoroffset(A4),D0     ; add possible shift to 11-20 sector #
  417.         move.b  D0,(A2)+                ; plug it into sector table
  418.  
  419. ; Add 1 to sector #. If it is b, wrap it to 1.
  420.         addi.w  #1,twistsectorno(A4)        ; real sector # being plopped
  421.         cmpi.w  #0xb,twistsectorno(A4)
  422.         bne     notb
  423.         move.w  #1,twistsectorno(A4)
  424. ;
  425. notb:   nop
  426.         move.b  #0x02,(A2)+              ; sector size (512)
  427.         move.b  #0xf7,(A2)+              ; write checksum
  428.  
  429. ;--- gap between AM and data:
  430.         move.w  #22-1,D1                ; 22 x 0x4e
  431.         move.b  #0x4e,D0
  432.         bsr     wmult
  433.         move.w  #12-1,D1                ; 12 x 0x00
  434.         clr.b   D0
  435.         bsr     wmult
  436.         move.w  #3-1,D1                 ; 3 x 0xf5
  437.         move.b  #0xf5,D0
  438.         bsr     wmult
  439.  
  440. ;--- data block:
  441.         move.b  #0xfb,(A2)+              ; 0xfb -- data intro
  442.         move.w  #256-1,D1               ; 256 x virgin.w (initial sector data)
  443. ot2:    move.b  virgin(A4),(A2)+            ; copy high byte
  444.         move.b  virgin+1(A4),(A2)+          ; copy low byte
  445.         dbf     D1,ot2                  ; fill 512 bytes
  446.         move.b  #0xf7,(A2)+              ; 0xf7 -- write checksum
  447.         move.w  #40-1,D1                ; 40 x 0x4e
  448.         move.b  #0x4e,D0
  449.         bsr     wmult
  450. ;
  451. ; Next sector, or, end-of-track. If we hit sector 11, time to quit.
  452. ;
  453.         addi.w   #1,sectorno(A4)
  454.         cmpi.w  #11,sectorno(A4)
  455.         bne     secloop         ; loop again
  456. ;
  457. ; Okay, 10 sectors laid down. 
  458. ;
  459. ;--- end-of-track
  460.         move.w  #1400,D1                ; 1401 x 0x4e -- end of track trailer
  461.         move.b  #0x4e,D0
  462.         bsr     wmult
  463.  
  464. ;--- setup to write the track:
  465.         move.b  cdma+3(A4),dmalow   ; load dma pointer
  466.         move.b  cdma+2(A4),dmamid
  467.         move.b  cdma+1(A4),dmahigh
  468.         move.w  #0x190,(A6)              ; toggle R/W flag and
  469.         move.w  #0x090,(A6)              ; select sector-count register
  470.         move.w  #0x190,(A6)
  471.         move.w  #0x1f,D7                 ; (absurd sector count)
  472.         bsr     wdiskctl
  473.         move.w  #0x180,(A6)              ; select 1770 cmd register
  474.         move.w  #0xf0,D7                 ; write format_track command
  475. ;debug* move.l  #0xff00ff00,0xfc030
  476.         bsr     wdiskctl
  477.         move.l  #timeout,D7             ; D7 = timeout value
  478.  
  479. ;--- wait for 1770 to complete:
  480. otw1:   btst.b  #5,gpip                 ; is 1770 done?
  481.         beq     otw2                    ; (yes)
  482.         subq.l  #1,D7                   ; if(--D7) continue;
  483.         bne     otw1
  484. ;debug* move.l  #0xffffffff,0xfc030
  485.  
  486.         bsr     reset1770               ; timed out -- reset 1770
  487. oterr:  moveq   #1,D7                   ; return NE (error status)
  488.         rts
  489.  
  490. ;--- see if the write-track won:
  491. otw2:   nop
  492. ;debug* move.l  #0x0,0xfc030
  493.  
  494.         move.w  #0x190,(A6)              ; check DMA status bit
  495.         move.w  (A6),D0
  496.         btst    #0,D0                   ; if its zero, there was a DMA error
  497.         beq     oterr                   ; (so return NE)
  498.         move.w  #0x180,(A6)              ; get 1770 status
  499.         bsr     rdiskctl
  500. ;**     bsr     err_bits                ; set 1770 error bits
  501.         and.b   #0x44,D0                 ; check for writeProtect & lostData
  502.         rts                             ; return NE on 1770 error
  503.  
  504. ;------ write 'D1+1' copies of D0.B into A2, A2+1, ...
  505. wmult:  move.b  D0,(A2)+                ; record byte in proto buffer
  506.         dbf     D1,wmult                ; (do it again)
  507.         rts
  508. ;
  509. ;************************************************************
  510. ;
  511. ; floplock - lock floppies and setup floppy parameters
  512. ;
  513. ; Passed (on the stack):
  514. ;       0x18(A7) - count.W (sector count)
  515. ;       0x16(A7) - side.W (side#)
  516. ;       0x14(A7) - track.W (track#)
  517. ;       0x12(A7) - sect.W (sector#)
  518. ;       0x10(A7) - dev.W (device#)
  519. ;        0xc(A7) - obsolete.L
  520. ;         8(A7) - dma.L (dma pointer)
  521. ;         4(A7) - ret1.L (caller's return address)
  522. ;         0(A7) - ret.L (floplock's return address)
  523. ;
  524. ; It is not coincidence that this matches the read and write input list;
  525. ; they call us to get stuff off stack and plug into parameters. Then,
  526. ; routine "select" actually pops this stuff into hardware.
  527. ;
  528. ; Passed:       D0.W = default error number
  529. ;
  530. ; Also, we helpfully point A6 at the DMA chip, and A1 at the DSB.
  531. ;-
  532. floplock:
  533.         lea    regsave, A0
  534.         movem.l D3-D7/A3-A6, (A0)       ; save C registers
  535.         lea     fifo,A6                 ; A6 -> fifo
  536. ; Start setting up param block..
  537.         move.w  D0,def_error(A4)            ; set default error number
  538.         move.w  D0,curr_err(A4)             ; set current error number
  539. ; Kick VBL off floppies..
  540.         move.w  #1,flock                ; tell vbl not to touch floppies
  541. ; Stuff off stack:
  542.         move.l  8(A7),cdma(A4)              ; cdma -> /even/ DMA address
  543.         move.w  0x10(A7),cdev(A4)    ; save device# (0 .. 1)
  544.         move.w  0x12(A7),csect(A4)   ; save sector# (1 .. 9, usually)
  545.         move.w  0x14(A7),ctrack(A4)  ; save track# (0 .. 39 .. 79 ..)
  546.         move.w  0x16(A7),cside(A4)   ; save side# (0 .. 1)
  547.         move.w  0x18(A7),ccount(A4)  ; save sector count (1..A)
  548. ;--- pick a DSB: Point A1 at it.
  549. ; we need to check which ROMs also, if old use that
  550. ; otherwise assume it is a new machine
  551.         lea     dsb0new,A1         ; pick dsb 0 (drive A)
  552.         cmpi.l  #old_rom, rom_date
  553.         bne     rom1
  554.         lea    dsb0old,A1
  555. rom1:   tst.w   cdev(A4)
  556.         beq     flock2
  557.         lea     dsb1new,A1         ; pick dsb 1 (drive B)
  558.         cmpi.l  #old_rom, rom_date
  559.         bne     flock2
  560.         lea     dsb1old,A1
  561. ;--- compute ending DMA address from count parameter: Plug into edma.
  562. ; This is used in multisector transfers in read-multiple-sector,
  563. ; but we don't use it here.
  564. flock2: moveq   #0,D7
  565.         move.w  ccount(A4),D7               ; edma = cdma + (ccount * 512)
  566.         lsl.w   #8,D7
  567.         lsl.w   #1,D7                   ; do a 9 shift..
  568.         movea.l  cdma(A4),A0
  569.         adda.l   D7,A0
  570.         move.l  A0,edma(A4)                 ; save in edma
  571. ;--- recalibrate drive, if it needs it. This only happens when the DSB
  572. ; says that this drive has never awoken before, and needs an initial
  573. ; recal to match its current track # with the DSB track #. 
  574.         tst.w   dcurtrack(A1)           ; if (curtrack < 0) recalibrate()
  575.         bpl     flockr
  576. ; RECAL needed. Show flag about it..
  577.         move.l  #0xf0f0f0f0,0xfe000
  578.         move.l  #0xf0f0f0f0,0xfe004
  579.  
  580.         bsr     select                  ; select drive & side
  581.         clr.w   dcurtrack(A1)           ; we're optimistic -- assume winnage
  582. ; Restore.
  583.         bsr     restore                 ; attempt restore
  584.         beq     flockr                  ; (it won)
  585.         moveq   #10,D7                  ; attempt seek to track 10
  586.         bsr     hseek1
  587.         bne     flock1                  ; (failed)
  588.         bsr     restore                 ; attempt restore again
  589.         beq     flockr                  ; (it won)
  590. ;
  591. flock1:  move.w  #recal, dcurtrack(A1)    ; complete failure (what can we do?)
  592.  
  593.         movem.l regsave(PC), D3-D7/A3-A6
  594. flockr: rts
  595. ;
  596. ;********************************************************************
  597. ;+
  598. ; flopfail - unlock floppies and return error.
  599. ; Common way for read and write to return.
  600. ;
  601. ; Note: Returns via unlok1.
  602. ;-
  603. flopfail:
  604.         move.l  #0xffffffff,D0           ; aargh, error
  605.         bra.s   unlok1                  ; clobber floppy lock & return
  606. ;***************************************************
  607. ;+
  608. ; flopok - unlock floppies and return success status. Also a common
  609. ; way for r/w to return.
  610. ;
  611. ;-
  612. flopok: clr.l   D0                      ; return 0 (success)
  613. ; Entry point from flopfail..
  614. unlok1: move.l  D0,-(A7)                ; (save return value)
  615. ; I believe this code returns the FDC's status to a type-1 status, where
  616. ; the write protect switch is available for VBL to look at.
  617.         move.w  #datareg,(A6)           ; force WP to real-time mode
  618. ; Sets FDC's current track register to track we are on right now.
  619.         move.w  dcurtrack(A1),D7        ; dest-track = current track
  620.         bsr     wdiskctl
  621. ; Does it with a "noop seek" (source=dest). Only forces FDC to type 1 status.
  622.         move.w  #0x10,D6                 ; cmd = seek w/o verify
  623.         bsr     flopcmds                ; do it
  624. ;
  625. unlok2: move.l  (A7)+,D0                ; restore return value
  626.         movem.l  regsave(PC), D3-D7/A3-A6
  627. ; clear floppy lock of vblank..
  628.         clr.w   flock                   ; allow vblank .. unlock floppies
  629. ; wave byebye at the pretty camera, jenny...
  630.         rts
  631. ;************************ Seek routines ********************
  632. ;+
  633. ; hseek  - seek to 'ctrack(A4)' without verify
  634. ; hseek1 - seek to 'D7' without verify
  635. ; hseek2 - seek to 'D7' without verify, keep current error number
  636. ;
  637. ; Returns:      NE on seek failure ("cannot happen"?)
  638. ;               EQ if seek wins
  639. ;
  640. ; Uses:         D7, D6, ...
  641. ; Exits to:     flopcmds
  642. ; Called-by:    _flopfmt, _flopini
  643. ;
  644. ;-
  645. hseek:  move.w  ctrack(A4),D7               ; dest track = 'ctrack'
  646. hseek1: nop
  647. hseek2: move.w  #datareg,(A6)           ; write destination track# to data reg
  648.         bsr     wdiskctl                ; write D7 to FDC data register
  649. ; seek command:
  650.         move.w  #0x10,D6                 ; execute "seek" command
  651. ;                                       * Note: no spinup time.
  652.         bra     flopcmds                ; (without verify...)
  653. ;
  654. ;***********************************************
  655. ;+
  656. ; reseek - home head, then reseek track
  657. ; Returns:      EQ/NE on success/failure
  658. ; Falls-into:   go2track
  659. ;
  660. ;-
  661. reseek:
  662.         bsr     restore                 ; restore head
  663.         bne     go2trr                  ; (punt if home fails)
  664.  
  665.         clr.w   dcurtrack(A1)           ; current track = 0
  666.         move.w  #trkreg,(A6)            ; set "current track" reg on 1770
  667.         clr.w   D7
  668.         bsr     wdiskctl                ; write a 00 to trk register.
  669.  
  670.         move.w  #datareg,(A6)           ; seek out to track five
  671.         move.w  #5,D7
  672.         bsr     wdiskctl                ; dest track = 5
  673.         move.w  #0x10,D6
  674.         bsr     flopcmds                ; seek
  675. ;                                       * Note: no spinup time.
  676.         bne     go2trr                  ; return error on seek failure
  677.         move.w  #5,dcurtrack(A1)        ; set current track#
  678.  
  679. ;***********************************************+
  680. ; go2track - seek proper track
  681. ; Passed:       Current floppy parameters (ctrack, et al.).
  682. ; Returns:      EQ/NE on success/failure
  683. ; Calls:        flopcmds
  684. ; Called by: read sector, for instance. Lots of places.
  685. ;-
  686. go2track:
  687.         move.w  #datareg,(A6)           ; set destination track# in
  688.         move.w  ctrack(A4),D7               ;  1770's data register
  689.         bsr     wdiskctl                ; (write track#)
  690.         moveq   #0x14,D6                 ; execute 1770 "seek_with_verify"
  691.         bsr     flopcmds                ; (include seek-rate bits)
  692.         bne     go2trr                  ; return error on seek failure
  693.         move.w  ctrack(A4),dcurtrack(A1)    ; update current track number
  694.         and.b   #0x18,D7                 ; check for RNF, CRC_error, lost_data
  695. go2trr: rts                             ; return EQ/NE on succes/failure
  696.  
  697. ;*************************************************
  698. ;+
  699. ; restore - home head
  700. ; Passed:       nothing
  701. ; Returns:      EQ/NE on success/failure
  702. ;-
  703. restore:
  704.         clr.w   D6                      ; 0x00 = 1770 "restore" command
  705.         bsr     flopcmds                ; do restore
  706.         bne     res_r                   ; punt on timeout
  707.         btst    #2,D7                   ; test TRK00 bit
  708.         eori.w  #0x04, CCR              ; flip Z bit (return NE if bit is zero)
  709.         bne     res_r                   ; punt if didn't win
  710.         clr.w   dcurtrack(A1)           ; set current track#
  711. res_r:  rts
  712.  
  713. ;****************************************************
  714. ; Special floppy cmd just for seeking:
  715. ;+
  716. ; flopcmds - floppy command (or-in seek speed bits from database)
  717. ; Passed:       D6.w = 1770 command
  718. ; Sets-up:      seek bits (bits 0 and 1) in D6.w
  719. ; Falls-into:   flopcmd
  720. ; Returns:      EQ/NE on success/failure
  721. ;
  722. ; I get the impression this is only used for seeking. I am right.
  723. ;-
  724. flopcmds:
  725.         move.w  dseekrt(A1),D0          ; get floppy's seek rate bits
  726.         andi.b  #3,D0                   ; OR into command
  727.         or.b    D0,D6
  728. ; Fall in...
  729. ;******************************************************+
  730. ; flopcmd - execute any ol' 1770 command (with timeout)
  731. ; Passed:       D6.w = 1770 command
  732. ;
  733. ; Returns:      EQ/NE on success/failure
  734. ;               D7 = 1770 status bits
  735. ;
  736. ; Note: does motor spinup, if cmd in D6 specs it (I would *hope*!)
  737. ;-
  738. flopcmd:
  739.         move.l  #timeout,D7             ; setup timeout count (assume short)
  740.         move.w  #cmdreg,(A6)            ; select 1770 command register
  741.         bsr     rdiskctl                ; read it to clobber READY status
  742.         btst    #7,D0                   ; is motor on?
  743.         bne     flopcm                  ; (yes, keep short timeout)
  744.         move.l  #ltimeout,D7            ; extra timeout for motor startup
  745. flopcm: bsr     wdiskct6                ; write command (in D6)
  746.  
  747. flopc1: subq.l  #1,D7                   ; timeout?
  748.         beq     flopcto                 ; (yes, reset and return failure)
  749.         btst.b  #5,gpip                 ; 1770 completion?
  750.         bne     flopc1                  ; (not yet, so wait some more)
  751.         bsr     rdiskct7                ; return EQ + 1770 status in D7
  752.         clr.w   D6
  753.         rts
  754. ;****
  755. flopcto:
  756. ; We timed out.. a gruesome death indeed.
  757. ; Whap controller back to life.    (Hit him harder Dave, he likes it that way)
  758.         bsr     reset1770               ; bash controller
  759.         moveq   #1,D6                   ; and return NE
  760.         rts
  761.  
  762. ;*******************************************************
  763. ;+
  764. ; reset1770 - reset disk controller after a catastrophe
  765. ; Passed:       nothing
  766. ; Returns:      nothing
  767. ; Uses:         D7
  768. ;-
  769. reset1770:
  770.         move.w  #cmdreg,(A6)            ; execute 1770 "reset" command
  771.         move.w  #0xD0,D7                 ; force interrupt
  772.         bsr     wdiskctl
  773.         move.w  #15,D7                  ; wait for 1770 to stop convulsing
  774. r1770:  dbf     D7,r1770                ; (short delay loop)
  775.         bsr     rdiskct7                ; return 1770 status in D7
  776.         rts
  777.  
  778. ;******************************************************
  779. ;+
  780. ; select - setup drive select, 1770 and DMA registers
  781. ; Passed:       cside(A4), cdev(A4)
  782. ; Returns:      appropriate drive and side selected
  783. ;
  784. ; Called: All over the place.
  785. ;
  786. ;-
  787. select: move.w  #0,0x9c0                 ; floppies NOT deselected
  788. ;                                       * lets VBL shut them off...
  789.         move.w  cdev(A4),D0                 ; get device number
  790.         addq.b  #1,D0                   ; add and shift to get select bits
  791.         lsl.b   #1,D0                   ; into bits 1 and 2
  792.         or.w    cside(A4),D0                ; or-in side number (bit 0)
  793.         eori.b   #7,D0                   ; negate bits for funky hardware select
  794.         andi.b   #7,D0                   ; strip anything else out there
  795.         bsr     setporta                ; do drive select
  796. ; Have to restore 1770's track register from table..in dsb.
  797.         move.w  #trkreg,(A6)            ; setup 1770 track register
  798.         move.w  dcurtrack(A1),D7        ; from current track number
  799.         bsr     wdiskctl
  800.         clr.b   tmpdma(A4)                  ; zero bits 24..32 of target DMA addr
  801.  
  802. ; Setup R/W parameters on 1770. Used by
  803. ; r/w sector, among others. This is where the sector register gets set.
  804. select1:
  805.         move.w  #secreg,(A6)            ; setup requested sector_number from
  806.         move.w  csect(A4),D7                ;       caller's parameters
  807.         bsr     wdiskctl
  808.         move.b  cdma+3(A4),dmalow           ; setup DMA chip's DMA pointer
  809.         move.b  cdma+2(A4),dmamid
  810.         move.b  cdma+1(A4),dmahigh
  811.         rts
  812.  
  813. ;************************************************
  814. ;+
  815. ; setporta - set floppy select bits in PORT A on the sound chip
  816. ; Passed:       D0.b (low three bits)
  817. ; Returns:      D1 = value written to port A
  818. ;               D2 = old value read from port A
  819. ; Uses:         D1
  820. ;-
  821. setporta:
  822.         move    SR,-(A7)                ; save our IPL
  823.         ori     #0x0700,SR               ; start critical section
  824.         move.b  #giporta,giselect       ; select port on GI chip
  825.         move.b  giread,D1               ; get current bits
  826.         move.b  D1,D2                   ; save old bits for caller
  827.         andi.b   #0xff-7,D1               ; strip low three bits there
  828.         or.b    D0,D1                   ; or-in our new bits
  829.         move.b  D1,giwrite              ; and write 'em back out there
  830.         move    (A7)+,SR                ; restore IPL to terminate CS, return
  831.         rts
  832.  
  833. ;**************************************************
  834. ;+
  835. ; Primitives to read/write 1770 controller chip (DISKCTL register).
  836. ;
  837. ; The 1770 can't keep up with full-tilt CPU accesses, so
  838. ; we have to surround reads and writes with delay loops.
  839. ; This is not really as slow as it sounds.
  840. ;
  841. wdiskct6:                               ; write D6 to diskctl
  842.         bsr     rwdelay                 ;       delay
  843.         move.w  D6,diskctl              ;       write it
  844.         bra     rwdelay                 ;       delay and return
  845.  
  846. wdiskctl:                               ; write D7 to diskctl
  847.         bsr     rwdelay                 ;       delay
  848.         move.w  D7,diskctl              ;       write it
  849.         bra     rwdelay                 ;       delay and return
  850.  
  851. rdiskct7:                               ; read diskctl into D7
  852.         bsr     rwdelay                 ;       delay
  853.         move.w  diskctl,D7              ;       read it
  854.         bra     rwdelay                 ;       delay and return
  855.  
  856. rdiskctl:                               ; read diskctl into D0
  857.         bsr     rwdelay                 ;       delay
  858.         move.w  diskctl,D0              ;       read it
  859. ; And here's the delay loop:
  860. rwdelay:
  861.         move    SR,-(A7)                ; save flags
  862.         move.w  D7,-(A7)                ; save counter register
  863.         move.w  #0x20,D7                ; 0x20 seems about right...
  864. rwdly1: dbf     D7,rwdly1               ; busy-loop: give 1770 time to settle
  865.         move.w  (A7)+,D7                ; restore register, flags, and return
  866.         move    (A7)+,SR
  867.         rts
  868.  
  869. ;-------------------------------------
  870. regsave:  dc.l      1      ; PC relative data area
  871.           dc.l      2
  872.           dc.l      3
  873.           dc.l      4
  874.           dc.l      5
  875.           dc.l      6
  876.           dc.l      7
  877.           dc.l      8
  878.           dc.l      9
  879.  
  880.  
  881. }         /* MY GOD!  It's DONE!  */
  882.